Skip to content

Method: setupActiveFields(Map, AtomicReference)

1: /*
2: * Copyright © 2021-2023 Fachhochschule für die Wirtschaft (FHDW) Hannover
3: *
4: * This file is part of ipspiel24-VierConnects-gui.
5: *
6: * ipspiel24-VierConnects-gui is free software: you can redistribute it and/or modify it under
7: * the terms of the GNU General Public License as published by the Free Software
8: * Foundation, either version 3 of the License, or (at your option) any later
9: * version.
10: *
11: * ipspiel24-VierConnects-gui is distributed in the hope that it will be useful, but WITHOUT
12: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14: * details.
15: *
16: * You should have received a copy of the GNU General Public License along with
17: * ipspiel24-VierConnects-gui. If not, see <http://www.gnu.org/licenses/>.
18: */
19: package de.fhdw.gaming.ipspiel24.VierConnects.gui.impl;
20:
21: import java.util.ArrayList;
22: import java.util.Collection;
23: import java.util.LinkedHashMap;
24: import java.util.List;
25: import java.util.Map;
26: import java.util.concurrent.atomic.AtomicReference;
27:
28: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsBoard;
29: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsField;
30: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsFieldState;
31: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsPlayer;
32: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsPosition;
33: import de.fhdw.gaming.ipspiel24.VierConnects.core.domain.VierConnectsState;
34: import de.fhdw.gaming.ipspiel24.VierConnects.gui.VierConnectsBoardEventProvider;
35: import de.fhdw.gaming.ipspiel24.VierConnects.gui.event.VierConnectsBoardEvent;
36: import de.fhdw.gaming.ipspiel24.VierConnects.gui.event.VierConnectsMakeMoveBoardEvent;
37: import javafx.application.Platform;
38: import javafx.scene.Cursor;
39: import javafx.scene.input.MouseButton;
40: import javafx.scene.input.MouseEvent;
41:
42: /**
43: * Implements user interaction with a VierConnects board.
44: */
45: final class VierConnectsBoardEventProviderImpl implements VierConnectsBoardEventProvider {
46:
47: /**
48: * The associated {@link VierConnectsBoardView}.
49: */
50: private final VierConnectsBoardView boardView;
51:
52: /**
53: * Constructor.
54: *
55: * @param boardView The associated {@link VierConnectsBoardView}.
56: */
57: VierConnectsBoardEventProviderImpl(final VierConnectsBoardView boardView) {
58: this.boardView = boardView;
59: }
60:
61: @Override
62: public VierConnectsBoardEvent waitForEvent(final VierConnectsPlayer player, final VierConnectsState state) {
63: final Map<VierConnectsPosition, VierConnectsFieldView> emptyFieldViews = new LinkedHashMap<>();
64: for (final Map.Entry<VierConnectsPosition, ? extends VierConnectsField> entry : state.getBoard()
65: .getFieldsBeing(VierConnectsFieldState.EMPTY).entrySet()) {
66: emptyFieldViews.put(entry.getKey(), this.boardView.getFieldView(entry.getKey()).orElseThrow());
67: }
68:
69: final AtomicReference<VierConnectsBoardEvent> event = new AtomicReference<>();
70: final Runnable cleanUp;
71: if (emptyFieldViews.isEmpty()) {
72: final List<VierConnectsFieldView> fieldViews = this.setupInactiveFields(state.getBoard());
73: cleanUp = () -> this.cleanUpFields(fieldViews);
74: } else {
75: this.setupActiveFields(emptyFieldViews, event);
76: cleanUp = () -> this.cleanUpFields(emptyFieldViews.values());
77: }
78:
79: try {
80: this.boardView.getUserInputSemaphore().acquire();
81: return event.get();
82: } catch (final InterruptedException e) {
83: return null;
84: } finally {
85: Platform.runLater(cleanUp);
86: }
87: }
88:
89: /**
90: * Sets up the fields when a move is possible (and hence the set of empty fields is not empty).
91: *
92: * @param emptyFieldViews The non-empty set of views for active fields.
93: * @param event The event to be set when the user selects an active field.
94: */
95: private void setupActiveFields(final Map<VierConnectsPosition, VierConnectsFieldView> emptyFieldViews,
96: final AtomicReference<VierConnectsBoardEvent> event) {
97:• for (final Map.Entry<VierConnectsPosition, VierConnectsFieldView> entry : emptyFieldViews.entrySet()) {
98: final VierConnectsPosition position = entry.getKey();
99: final VierConnectsFieldView fieldView = entry.getValue();
100: Platform.runLater(() -> {
101: fieldView.setCursor(Cursor.CROSSHAIR);
102: fieldView.setHighlighted(true);
103: fieldView.setOnMouseClicked((final MouseEvent mouseEvent) -> {
104: if (mouseEvent.getButton() == MouseButton.PRIMARY) {
105: event.set(new VierConnectsMakeMoveBoardEvent(position));
106: this.boardView.getUserInputSemaphore().release();
107: }
108: });
109: });
110: }
111: }
112:
113: /**
114: * Sets up the fields when no move is possible (and hence the set of empty fields is empty).
115: *
116: * @param board The Vier Connects board.
117: * @return A list of all field views on the board.
118: */
119: private List<VierConnectsFieldView> setupInactiveFields(final VierConnectsBoard board) {
120: final List<VierConnectsField> fields = new ArrayList<>();
121: board.getFields().forEach((final List<? extends VierConnectsField> list) -> fields.addAll(list));
122:
123: final List<VierConnectsFieldView> fieldViews = new ArrayList<>();
124: for (final VierConnectsField field : fields) {
125: final VierConnectsFieldView fieldView = this.boardView.getFieldView(field.getPosition()).orElseThrow();
126: fieldViews.add(fieldView);
127: Platform.runLater(() -> {
128: fieldView.setCursor(Cursor.CLOSED_HAND);
129: fieldView.setOnMouseClicked(null);
130: });
131: }
132:
133: return fieldViews;
134: }
135:
136: /**
137: * Cleans up after user interaction by resetting mouse cursors and removing event handlers.
138: *
139: * @param fieldViews The modified field views.
140: */
141: private void cleanUpFields(final Collection<? extends VierConnectsFieldView> fieldViews) {
142: for (final VierConnectsFieldView fieldView : fieldViews) {
143: fieldView.setCursor(Cursor.DEFAULT);
144: fieldView.setHighlighted(false);
145: fieldView.setOnMouseClicked(null);
146: }
147: }
148:
149: @Override
150: public void cancelWaiting() {
151: this.boardView.getUserInputSemaphore().release();
152: }
153: }